package com.ysq.www.common.exception;

import com.ysq.www.common.result.ResultMsg;
import com.ysq.www.common.result.ResultStatusCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import redis.clients.jedis.exceptions.JedisConnectionException;
import redis.clients.jedis.exceptions.JedisException;

import javax.validation.ConstraintViolationException;

/**
 * 类描述: 全局异常拦截处理器
 *   1.处理自定义异常
 *   2.未知异常统一返回服务器错误
 *   3.已经catch到的异常不会被捕获
 *   4.异常的体系结构中，哪个异常与目标方法抛出的异常血缘关系越紧密，就会被哪个捕捉到。
 *  @see ExceptionHandler ：统一处理某一类异常，从而能够减少代码重复率和复杂度
 *  @see /ControllerAdvice：异常集中处理，更好的使业务逻辑与异常处理剥离开
 *  @see /ResponseStatus：可以将某种异常映射为HTTP状态码 成功则Status Code: 200
 */
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    /**
     * Bad Request
     */
    @ExceptionHandler({HttpMessageNotReadableException.class, MissingServletRequestParameterException.class, BindException.class,
            ServletRequestBindingException.class, MethodArgumentNotValidException.class, ConstraintViolationException.class})
    public ResultMsg handleHttpMessageNotReadableException(Exception e){
        log.error("参数解析失败!",e);
        if (e instanceof BindException){
            return new ResultMsg(ResultStatusCode.BAD_REQUEST.getCode(),((BindException)e).getAllErrors().get(0).getDefaultMessage());
        }
        return new ResultMsg(ResultStatusCode.BAD_REQUEST.getCode(),e.getMessage());
    }


    /**
     *  405 - Method Not Allowed
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public ResultMsg handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e){
        log.error("不支持当前请求方法",e);
        return new ResultMsg(ResultStatusCode.METHOD_NOT_ALLOWED);
    }


    /**
     * 其他全局异常在此捕获
     */
    @ExceptionHandler(Throwable.class)
    public ResultMsg handleException(Exception e){
        log.error("服务运行异常",e);
        if (e instanceof JedisConnectionException){
            //redis连接异常
            return new ResultMsg(ResultStatusCode.REDIS_CONNECT_ERROR);
        }else if (e instanceof JedisException){
            //redis异常
            return new ResultMsg(ResultStatusCode.REDIS_ERROR);
        }else if (e instanceof BaseException){
            return new ResultMsg(ResultStatusCode.SYSTEM_ERR);
        }
        return ResultMsg.UNKNOWN_ERROR;
    }



}
